package com.ryan.spring.annotation.ext;

import com.ryan.spring.annotation.model.Car;
import com.ryan.spring.annotation.model.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * Created by kaimin on 14/2/2019.
 * time : 22:14
 * 扩展原理
 * BeanPostProcessor bean后置处理器，在bean创建对象初始化前后进行拦截，可以对bean对象进行修改
 * BeanFactoryPostProcessor beanFacotry后置处理器，在bean factory标准初始化，即所有的bean定义已经保存加载
 * 到beanfactory中，但是bean的实例还没有创建
 * 所以可以对bean定义进行修改，比如bean的scope等
 *
 * 流程：
 * 1、BeanFactoryPostProcessor原理
 *      1、IOC容器创建对象
 *      2、invokeBeanFactoryPostProcessors。执行BeanFactoryPostProcessors
 *          如何找到所有的BeanFactoryPostProcessors并执行其方法
 *              1、直接在BeanFactory中找到所有类型是BeanFactoryPostProcessors的组件，并且执行它们的方法
 *              2、在初始化创建其它组件前面执行
 *
 *     2、BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
 *      方法 postProcessBeanDefinitionRegistry
 *      在所有的bean定义信息将要被加载，bean实例还没有创建
 *
 *      优先与BeanFactoryPostProcessor，【为什么？看原理】
 *      该接口可以利用起来，手动向容器中注册bean，或者其它一些组件
 *      原理：
 *      1、创建 iOC容器
 *      2、refresh()==》invokeBeanFactoryPostProcessors
 *      3、从容器中获取所有的BeanDefinitionRegistryPostProcessor组件，
 *         1、依次触发所有的postProcessBeanDefinitionRegistry
 *         2、再触发postProcessBeanFactory()方法
 *      4、再从容器中找到BeanFactoryPostProcessor组件，依次触发postProcessBeanFactory()方法
 *
 *  3、ApplicationListener<E extends ApplicationEvent> extends EventListener
 *      监听容器中发布的事件，事件驱动模型开发
 *      监听ApplicationEvent及子类
 *      可以自己去写一个事件,也可以加@EventListener注解
 *         注解的原理：使用EventListenerMethodProcessor来解析方法上的注解
 *          该处理器实现了SmartInitializingSingleton
 *              SmartInitializingSingleton原理：
 *                  1、创建容器
 *                  2、刷新容器
 *                  3、finishBeanFactoryInitialization(beanFactory);
 *                      1、先创建所有的单实例bean，getBean（）
 *                      2、获取所有创建好的单实例bean，判断是否是SmartInitializingSingleton类型，如果是就调用afterSingletonsInstantiated()：
 *                  4、smartSingleton.afterSingletonsInstantiated()：
 *
 *
 *      步骤；
 *          1、写一个监听器来监听某个事件（ApplicationEvent的子类）
 *          2、把监听器加入到容器中
 *          3、只要容器中有相关的事件发布，就能监听到这个事件
 *              ContextRefreshedEvent 容器刷新完成（所有的bean都已经创建）会发布这个事件
 *              ContextClosedEvent 关闭容器，会发布这个事件
 *          4、自己发布一个事件
 *              applicationContext.publishEvent();
 *              原理：
 *                  现在有三个事件，怎么接收的三个事件？
 *                  1、ContextRefreshedEvent
 *                      1、创建容器
 *                      2、刷新容器
 *                      3、finishRefresh();
 *                      4、publishEvent(new ContextRefreshedEvent(this));
 *                          事件发布流程：
 *                              1、获取事件的派发器getApplicationEventMulticaster()
 *                              2、multicastEvent 派发事件
 *                        【先获取所有的getApplicationListeners，1判断有没有Executor，进行异步派发 否则同步的方式执行listener】
 *                              3、拿到MyApplicationListner 执行onApplicationEvent方法
 *           不管是自己的事件还是容器自身的事件，都会走按事件的流程走
 *           事件多播器（ApplicationEventMulticaster）从哪儿获取的？
 *              1、容器init
 *              2、容器refresh（）==》initApplicationEventMulticaster();会初始化事件多播器
 *              3、init的时候如果有，就获取，没有就创建一个SimpleApplicationEventMulticaster并且加入到容器中
 *              ，可以在其它组件要派发事件的时候，自动租入这个SimpleApplicationEventMulticaster
 *
 *           怎么知道有哪些ApplicationListener呢？
 *           1、容器
 *           2、registerListeners()注册监听，加到多播器中
 *
 *           String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
 *
 *           getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

 *
 */
@Configuration
@ComponentScan("com.ryan.spring.annotation.ext")
public class ExtConfig {

    @Bean
    public Person person(){
        Person person = new Person();
        return person;
    }
}
